use std::cmp::max;
use std::path::Path;

use anyhow::Error;
use image::{GenericImageView, ImageBuffer};

use crate::common::{collect_images, Rect};
use crate::error::Res;

pub fn pack_tile_images<P: AsRef<Path>>(source_path: P, image_name_pattern: &str, output_file_name: P) -> Res<()> {
    let mut images = collect_images(source_path, image_name_pattern)?;
    if images.is_empty() {
        return Err(Error::msg("No matching images found"));
    }

    let grid_width = 64i32;
    let grid_height = 88i32;

    let img_len = images.len() as f64;
    let col_count = img_len.sqrt().ceil() as i32;

    let (width, height) = ((grid_width * col_count) as u32, (grid_height * col_count) as u32);

    let mut merged_image = ImageBuffer::new(width, height);

    let mut i = 0;
    for image in &images {
        let x = i % col_count;
        let y = i / col_count;
        let Rect { w, h, .. } = image.rect;
        let offset_x = x * grid_width + max((grid_width - w as i32) / 2, 0);
        let offset_y = y * grid_height + max(0, (grid_height - h as i32) / 2);
        for (xi, yi, pixel) in image.buffer.pixels() {
            let x = offset_x as u32 + xi;
            let y = offset_y as u32 + yi;
            if x < width && y < height {
                merged_image.put_pixel(x, y, pixel);
            }
        }
        i += 1;
    }

    merged_image.save(&output_file_name)?;

    Ok(())
}